package com.ruoyi.demo.util;

import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class MinIOUtil extends IOUtil {
    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucket}")
    private String bucket;

    @PostConstruct
    @Override
    public void init() {
        project = bucket;
        root = "";
        user = "user/";
        user_avatar = "avatar/";
        user_photos = "photos/";
        user_faceid = "faceid/";
        meet = root + "meet/";
        meet_audio = "audio/";
        meet_video = "video/";
        meet_photos = "photos/";
        try {
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket(project).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(project).build());
            }
        } catch (ErrorResponseException | XmlParserException | ServerException | NoSuchAlgorithmException |
                 IOException | InvalidResponseException | InternalException | InsufficientDataException |
                 InvalidKeyException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected String put(MultipartFile file, String uploadPath, String fileName) {
        try {
            InputStream inputStream = file.getInputStream();
            String filePath = uploadPath + fileName;
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(project)
                            .object(filePath)
                            .stream(
                                    inputStream, inputStream.available(), -1)
                            .build());
            inputStream.close();
            return filePath;
        } catch (ErrorResponseException e) {
            throw new RuntimeException(e);
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);
        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected String put(File file, String uploadPath, String fileName) {
        return "";
    }

    @Override
    protected byte[] getFileBytes(String filePath) {
        InputStream inputStream = getInputStream(filePath);
        try {
            byte[] bytes = inputStream.readAllBytes();
            inputStream.close();
            return bytes;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public MultipartFile getMultipartFile(String filePath) {
        MultipartFile multipartFile = new MockMultipartFile(Paths.get(filePath).getFileName().toString(), getFileBytes(filePath));
        return multipartFile;
    }

    /**
     * 本地文件转为MultipartFile
     * @param filePath
     * @return
     */
    @Override
    public MultipartFile getLocalMultipartFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            try {
                throw new FileNotFoundException("File not found: " + filePath);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        String fileName = Paths.get(filePath).getFileName().toString();
        log.info("fileName :{}",fileName);

        MultipartFile multipartFile = null;
        try {
            multipartFile = new MockMultipartFile(Paths.get(filePath).getFileName().toString(), new FileInputStream(file).readAllBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return multipartFile;
    }
    /**
     * 读取本地文件的字节数据
     */
    @Override
    public byte[] getLocalFileBytes(String localFilePath) throws IOException {
        File file = new File(localFilePath);
        if (!file.exists()) {
            throw new FileNotFoundException("File not found: " + localFilePath);
        }
        try (InputStream inputStream = new FileInputStream(file)) {
            return inputStream.readAllBytes();
        }
    }
    @Override
                protected File getFile(String filePath) {
        File file = null;
        try {
            file = getMultipartFile(filePath).getResource().getFile();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return file;
    }

    @Override
    protected InputStream getInputStream(String filePath) {
        try {
            if (isExist(filePath)) {
                InputStream inputStream = minioClient.getObject(
                        GetObjectArgs
                                .builder()
                                .bucket(project)
                                .object(filePath)
                                .build());
                return inputStream;
            } else {
                System.out.println(MinIOUtil.class + ": \"getInputStream(String filePath)\" can't find file");
                return null;
            }
        } catch (ErrorResponseException | InternalException | InsufficientDataException | InvalidKeyException |
                 InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |
                 XmlParserException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected OutputStream getOutputStream(String filePath) {
        return new MinioOutputStream(filePath);
    }

    @Override
    public boolean deleteFile(String filePath) {
        if (isExist(filePath)) {
            try {
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(project)
                                .object(filePath)
                                .build()
                );
                return true;
            } catch (RuntimeException | ErrorResponseException | InsufficientDataException | InternalException |
                     InvalidKeyException |
                     InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |
                     XmlParserException e) {
                System.out.println(e.getMessage());
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean isExist(String filepath) {
        try {
            // 获取对象的元数据
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(project)
                    .object(filepath)
                    .build());
            return true;
        } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
            return false;
        }
    }

    @Override
    public List<String> getFileList(String path) {
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(project)
                .prefix(path)
                .build());
        List<String> list = new ArrayList<>();
        for (Result<Item> result : results) {
            try {
                Item item = null;
                item = result.get();
                list.add(item.objectName().replace(path, ""));
            } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException |
                     InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |
                     XmlParserException e) {
                throw new RuntimeException(e);
            }
        }
        return list;
    }

    @Override
    public String uploadImage(MultipartFile file, String filePath, String fileName) {
        return put(file, filePath, fileName);
    }

    @Override
    public MultipartFile getImage(String filePath) {
        return getMultipartFile(filePath);
    }

    /**
     * 获取文件路径
     */
    public String generatePresignedUrl(String filePath, int expiryDurationMinutes) {

        try {
            // 生成临时的预签名 URL，有效期为 `expiryDurationMinutes` 分钟
            String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .bucket(bucket)
                    .object(filePath)
                    .method(Method.GET)
                    .expiry(expiryDurationMinutes, TimeUnit.MINUTES)
                    .build());

            // 直接返回URL的字符串表示
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 上传纪要到 MinIO
    @Override
    public String uploadSummaryToMinIO(String summary, String meet_id,String title,String basePath) {

        log.info("summary :{}",summary);

        // 获取当前时间戳
        long timestamp = System.currentTimeMillis();

        // 将时间戳转换为LocalDateTime对象
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());

        // 创建DateTimeFormatter对象，并设置所需的日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String formattedDate = dateTime.format(formatter); // 格式化时间戳为yyyyMMddHHmmssSSS格式


        String fileName = "summary" + "_" + meet_id + "_" + formattedDate + "_" + title +".txt";

        String summaryPath = meet + meet_id + basePath;


        InputStream inputStream = new ByteArrayInputStream(summary.getBytes(StandardCharsets.UTF_8));
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
        MultipartFile multipartFile=  new CommonsMultipartFile(fileItem);

        put(multipartFile,summaryPath,fileName);

        return fileName;


    }

    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {

            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    throw new IllegalArgumentException("流关闭出错");
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new IllegalArgumentException("流关闭出错");
                }
            }
        }

        return item;
    }
    /**
     * 上传会议议程视频
     * @param multipartFile
     * @param meet_id
     * @return
     */
    @Override
    public String uploadAgendaVideo(MultipartFile multipartFile, String meet_id) {
        String fileName = setUploadFileName(multipartFile, meet_id, "agendaVideo");
        log.info("agendaViddeoFilename",fileName);
        String filePath = meet + meet_id + "/agendaVideo/";
        uploadVideo(multipartFile, filePath, fileName);
        return fileName;
    }

    /**
     * 上传会议议程音频
     * @param multipartFile
     * @param meet_id
     * @return
     */
    @Override
    public String uploadAgendaAudio(MultipartFile multipartFile, String meet_id) {
        String fileName = setUploadFileName(multipartFile, meet_id, "agendaAudio");
        String filePath = meet + meet_id + "/agendaAudio/";
        uploadVideo(multipartFile, filePath, fileName);
        return fileName;
    }

    /**
     * 获取会议议程视频
     * @param
     * @return
     */
    @Override
    public MultipartFile getAgendaVideo(String fileName, String meet_id) {
        return getVideo(meet + meet_id + "/agendaVideo/" + fileName);
    }

    /**
     * 获取会议议程音频
     * @param
     * @return
     */
    @Override
    public MultipartFile getAgendaAudio(String fileName, String meet_id) {
        return getAudio(meet + meet_id + "/agendaAudio/" + fileName);
    }

    /**
     * 修改上传filename
     * @param multipartFile
     * @return
     */
    protected String setUploadFileName(MultipartFile multipartFile, String ID, String prefix) {
        //        确定文件名
        String originFileName = multipartFile.getName();
        String suffix = originFileName.substring(originFileName.lastIndexOf(".") + 1);
        Long timestamp = System.currentTimeMillis();
        // 将时间戳转换为LocalDateTime对象
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());

        // 创建DateTimeFormatter对象，并设置所需的日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddhhmmssSSS");
        String formattedDate = dateTime.format(formatter);
        String fileName = prefix + "_" + ID + "_" + formattedDate + "." + suffix;

        return fileName;
    }
    @Override
    public String uploadVideo(MultipartFile multipartFile, String path, String fileName) {
        return put(multipartFile, path, fileName);
    }

    @Override
    protected String uploadVideo(File file, String path, String fileName) {
        return put(file, path, fileName);
    }

    @Override
    protected OutputStream uploadVideoStream(String filePath) {
        return getOutputStream(filePath);
    }

    @Override
    public MultipartFile getVideo(String filePath) {
        return getMultipartFile(filePath);
    }

    @Override
    public InputStream getVideoStream(String filePath) {
        return getInputStream(filePath);
    }

    public byte[] getVideoBytes(String filePath) {
        return getFileBytes(filePath);
    }

    @Override
    public String uploadAudio(MultipartFile file, String path, String fileName) {
        return put(file, path, fileName);
    }

    @Override
    protected OutputStream uploadAudioStream(String filePath) {
        return getOutputStream(filePath);
    }

    @Override
    public MultipartFile getAudio(String filePath) {
        return getMultipartFile(filePath);
    }

    @Override
    public InputStream getAudioStream(String filePath) {
        return getInputStream(filePath);
    }

    @Override
    public String uploadUserAvatar(MultipartFile file, String user_id) {
        String fileName = setFileName(file, user_id, "userAvatar");
        String path = user + user_id + "/" + user_avatar;
        if (put(file, path, fileName) == null) {
            fileName = null;
        }
        return fileName;
    }

    @Override
    public MultipartFile getUserAvatar(String fileName, String user_id) {
        return getImage(user + user_id + "/" + user_avatar + fileName);
    }

    @Override
    public boolean deleteUserAvatar(String fileName, String user_id) {
        return deleteFile(user + user_id + "/" + user_avatar + fileName);
    }


    @Override
    public String uploadUserPhoto(MultipartFile file, String user_id) {
        String fileName = setFileName(file, user_id, "userPhoto");
        String path = user + user_id + "/" + user_photos;
        if (put(file, path, fileName) == null) {
            fileName = null;
        }
        return fileName;
    }

    @Override
    public MultipartFile getUserPhoto(String fileName, String user_id) {
        return getImage(user + user_id + "/" + user_photos + fileName);
    }

    @Override
    public List<String> getUserPhotoList(String user_id) {
        return getFileList(user + user_id + "/" + user_photos);
    }

    @Override
    public boolean deleteUserPhoto(String fileName, String user_id) {
        return deleteFile(user + user_id + "/" + user_photos + fileName);
    }

    @Override
    public MultipartFile getUserFace(String fileName, String user_id) {
        return getImage(user + user_id + "/" + user_photos + fileName);
    }

    @Override
    public List<String> getUserFaceList(String user_id) {
        return getFileList(user + user_id + "/" + user_faceid);
    }

    @Override
    public boolean deleteUserFace(String fileName, String user_id) {
        return deleteFile(user + user_id + "/" + user_faceid + fileName);
    }

    @Override
    public String uploadUserFaceID(MultipartFile file, String user_id) {
        String fileName = setFileName(file, user_id, "faceID");
        put(file, user + user_id + "/" + user_faceid, fileName);
        return user_id;
    }

    @Override
    public String uploadMeetPhoto(MultipartFile multipartFile, String meet_id) {
        String fileName = setFileName(multipartFile, meet_id, "meetPhoto");
//        上传文件
        put(multipartFile, meet + meet_id + "/" + meet_photos, fileName);
        return fileName;
    }

    @Override
    public MultipartFile getMeetPhoto(String fileName, String meet_id) {
        return getImage(meet + meet_id + "/" + meet_photos + fileName);
    }

    @Override
    public List<String> getMeetPhotoList(String meet_id) {
        return getFileList(meet + meet_id + "/" + meet_photos);
    }

    @Override
    public boolean deleteMeetPhoto(String fileName, String meet_id) {
        return deleteFile(meet + meet_id + "/" + meet_photos + fileName);
    }

    @Override
    public String uploadMeetVideo(MultipartFile multipartFile, String meet_id) {
        String fileName = setFileName(multipartFile, meet_id, "meetVideo");
        String filePath = meet + meet_id + "/" + meet_video;
        uploadVideo(multipartFile, filePath, fileName);
        return fileName;
    }

    @Override
    public MultipartFile getMeetVideo(String fileName, String meet_id) {
        return getVideo(meet + meet_id + "/" + meet_video + fileName);
    }

    @Override
    public List<String> getMeetVideoList(String meet_id) {
        return getFileList(meet + meet_id + "/" + meet_video);
    }


    @Override
    public boolean deleteMeetVideo(String fileName, String meet_id) {
        return deleteFile(meet + meet_id + "/" + meet_video + fileName);
    }

    @Override
    public InputStream getMeetVideoStream(String fileName, String meet_id) {
        return getVideoStream(meet_video + fileName);
    }

    @Override
    public String uploadMeetAudio(MultipartFile multipartFile, String meet_id) {
        String fileName = setFileName(multipartFile, meet_id, "meetAudio");
        return uploadAudio(multipartFile, meet + meet_id + "/" + meet_audio, fileName);
    }

    @Override
    public MultipartFile getMeetAudio(String fileName, String meet_id) {
        return getAudio(meet + meet_id + "/" + meet_audio + fileName);
    }

    @Override
    public List<String> getMeetAudioList(String meet_id) {
        return getFileList(meet + meet_id + "/" + meet_audio);
    }

    @Override
    public boolean deleteMeetAudio(String fileName, String meet_id) {
        return deleteFile(meet + meet_id + "/" + meet_audio + fileName);
    }

    @Override
    public InputStream getMeetAudioStream(String fileName, String meet_id) {
        return getInputStream(meet_audio + fileName);
    }

    @Override
    public void downloadFile(String remotePath, String localFilePath) {
        try {
            File localFile = new File(localFilePath);
            if (!localFile.getParentFile().exists()) {
                localFile.getParentFile().mkdirs();
            }

            // 获取文件名
            String fileName = new File(remotePath).getName();

            // 构建完整的路径
            String fullRemotePath = meet + getMeetIdFromPath(remotePath) + "/" + (remotePath.contains("meetVideo") ? meet_video : meet_audio) + fileName;

            // 使用 MinIO 客户端下载文件
            try (InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucket)
                            .object(fullRemotePath)
                            .build())) {

                // 将 InputStream 中的内容写入到本地文件
                Files.copy(inputStream, localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);

                log.info("文件下载完成：{}", localFilePath);
            } catch (IOException e) {
                log.error("文件下载失败：{}", localFilePath, e);
                throw new RuntimeException("下载文件失败: " + localFilePath, e);
            }

        } catch (ErrorResponseException e) {
            log.error("文件不存在：{}", remotePath);
            throw new RuntimeException("文件不存在: " + remotePath, e);
        } catch (Exception e) {
            log.error("下载文件失败：{}", localFilePath, e);
            throw new RuntimeException("下载文件失败: " + localFilePath, e);
        }
    }

    /**
     * 从路径中提取会议ID
     */
    private String getMeetIdFromPath(String path) {
        System.out.println("路径：" + path);
        // 假设文件名格式为 meetVideo_{meetId}_{timestamp}.mp4
        String[] parts = path.split("_");
        if (parts.length >= 2 && parts[1].matches("\\d+")) {
            return parts[1]; // 提取 meetId
        }
        throw new IllegalArgumentException("无法从路径中提取会议ID: " + path);
    }

    protected String setFileName(MultipartFile multipartFile, String ID, String prefix) {
        //        确定文件名
        String originFileName = multipartFile.getOriginalFilename();
        String suffix = originFileName.substring(originFileName.lastIndexOf(".") + 1);
        Long timestamp = System.currentTimeMillis();
        // 将时间戳转换为LocalDateTime对象
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());

        // 创建DateTimeFormatter对象，并设置所需的日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddhhmmssSSS");
        String formattedDate = dateTime.format(formatter);
        String fileName = prefix + "_" + ID + "_" + formattedDate + "." + suffix;

        return fileName;
    }


    private class MinioOutputStream extends OutputStream {

        private final String bucketName = project;
        private final String objectName;
        private final int chunkSize = 5 * 1024 * 1024;
        private final List<String> partNames = new ArrayList<>();
        private final ByteArrayOutputStream buffer;
        private boolean closed = false;

        public MinioOutputStream(String filePath) {
            this.objectName = filePath;
            this.buffer = new ByteArrayOutputStream(chunkSize);
        }

        @Override
        public void write(int b) throws IOException {
            if (closed) {
                throw new IOException("Stream is closed");
            }
            buffer.write(b);
            if (buffer.size() >= chunkSize) {
                flushBuffer();
            }
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (closed) {
                throw new IOException("Stream is closed");
            }
            int remaining = len;
            int offset = off;

            while (remaining > 0) {
                int chunkLength = Math.min(chunkSize - buffer.size(), remaining);
                buffer.write(b, offset, chunkLength);
                offset += chunkLength;
                remaining -= chunkLength;

                if (buffer.size() >= chunkSize) {
                    flushBuffer();
                }
            }
        }

        @Override
        public void close() throws IOException {
            if (closed) {
                return;
            }
            try {
                // 上传最后一个分块
                if (buffer.size() > 0) {
                    flushBuffer();
                }

                // 如果没有分块，直接上传空对象
                if (partNames.isEmpty()) {
                    minioClient.putObject(
                            PutObjectArgs.builder()
                                    .bucket(bucketName)
                                    .object(objectName)
                                    .stream(new ByteArrayInputStream(new byte[0]), 0, -1)
                                    .build()
                    );
                    return;
                }

                // 如果有多个分块，使用 composeObject 合并
                if (partNames.size() > 1) {
                    List<ComposeSource> sources = new ArrayList<>();
                    for (String partName : partNames) {
                        sources.add(ComposeSource.builder()
                                .bucket(bucketName)
                                .object(partName)
                                .build());
                    }

                    minioClient.composeObject(
                            ComposeObjectArgs.builder()
                                    .bucket(bucketName)
                                    .object(objectName)
                                    .sources(sources)
                                    .build()
                    );

                    // 删除临时分块
                    for (String partName : partNames) {
                        minioClient.removeObject(
                                RemoveObjectArgs.builder()
                                        .bucket(project)
                                        .object(partName)
                                        .build());
//                        minioClient.removeObject(bucketName, partName);
                    }
                } else {
                    // 如果只有一个分块，直接重命名
                    minioClient.copyObject(
                            CopyObjectArgs.builder()
                                    .bucket(bucketName)
                                    .object(objectName)
                                    .source(CopySource.builder()
                                            .bucket(bucketName)
                                            .object(partNames.get(0))
                                            .build())
                                    .build()
                    );
                    minioClient.removeObject(
                            RemoveObjectArgs.builder()
                                    .bucket(project)
                                    .object(partNames.get(0))
                                    .build());
                }

                closed = true;
            } catch (MinioException | InvalidKeyException | NoSuchAlgorithmException e) {
                throw new IOException("Failed to complete upload", e);
            }
        }

        private void flushBuffer() throws IOException {
            if (buffer.size() == 0) {
                return;
            }

            try {
                // 生成唯一的分块名称
                String partName = objectName + "-part-" + UUID.randomUUID();
                partNames.add(partName);

                // 上传分块
                byte[] chunkData = buffer.toByteArray();
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(bucketName)
                                .object(partName)
                                .stream(new ByteArrayInputStream(chunkData), chunkData.length, -1)
                                .build()
                );

                // 清空缓冲区
                buffer.reset();
            } catch (MinioException | InvalidKeyException | NoSuchAlgorithmException e) {
                throw new IOException("Failed to upload chunk", e);
            }
        }


    }

    }





